package com.hulk.dryad.web.oauth2.config;


import com.hulk.dryad.web.oauth2.base.service.DryadRedisTokenStore;
import com.hulk.dryad.web.oauth2.base.service.DryadUserDetailsService;
import com.hulk.dryad.web.oauth2.base.service.impl.DryadClientDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.sql.DataSource;

/**
 * @author hulk
 */
@Configuration
@ConditionalOnProperty(name = "token.store.enable", havingValue = "true", matchIfMissing = true)
public class TokenStoreConfig {


    /**
     * 使用jdbc时的配置，默认生效
     *
     * @author hulk
     */
    @Configuration
    @ConditionalOnProperty(name = "token.store.name", havingValue = "jdbc", matchIfMissing = false)
    public static class TokenStoreJdbcConfig {

        /**
         * JDBC TokenStore
         */
        @Bean
        public JdbcTokenStore jdbcTokenStore(DataSource dataSource) {
            return new JdbcTokenStore(dataSource);
        }


        @Bean
        public DefaultTokenServices defaultTokenServices(JdbcTokenStore jdbcTokenStore, DryadClientDetailsServiceImpl dryadClientDetailsServiceImpl) {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(jdbcTokenStore);
            tokenServices.setClientDetailsService(dryadClientDetailsServiceImpl);
            //support refresh token
            tokenServices.setSupportRefreshToken(true);
            return tokenServices;
        }


    }

    /**
     * 使用redis时的配置，默认生效
     *
     * @author hulk
     */
    @Configuration
    @ConditionalOnProperty(name = "token.store.name", havingValue = "redis", matchIfMissing = true)
    public static class TokenStoreReidsConfig {

        @Autowired
        private RedisConnectionFactory redisConnectionFactory;

        @Bean
        public DryadRedisTokenStore dryadRedisTokenStore() {
            return new DryadRedisTokenStore(redisConnectionFactory);
        }

        @Bean
        public DefaultTokenServices defaultTokenServices(DryadRedisTokenStore dryadRedisTokenStore, DryadClientDetailsServiceImpl dryadClientDetailsServiceImpl) {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(dryadRedisTokenStore);
            tokenServices.setClientDetailsService(dryadClientDetailsServiceImpl);
            //support refresh token
            tokenServices.setSupportRefreshToken(true);
            return tokenServices;
        }
    }

    /**
     * 使用jwt时的配置
     *
     * @author hulk
     */
    @Configuration
    @ConditionalOnProperty(name = "token.store.name", havingValue = "jwt", matchIfMissing = false)
    public static class TokenStoreJwtConfig {


        /**
         * HMAC key, default: IH6S2dhCEMwGr7uE4fBakSuDh9SoIrRa
         * alg: HMACSHA256
         */
        @Value("${token.store.jwt.key:IH6S2dhCEMwGr7uE4fBakSuDh9SoIrRa}")
        private String jwtKey;


        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(DryadUserDetailsService dryadUserDetailsService) {
            JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();

            DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
            DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
            userAuthenticationConverter.setUserDetailsService(dryadUserDetailsService);
//        userAuthenticationConverter.setDefaultAuthorities(new String[]{"USER"});
            tokenConverter.setUserTokenConverter(userAuthenticationConverter);
            tokenConverter.setIncludeGrantType(true);
//        tokenConverter.setScopeAttribute("_scope");
            jwtAccessTokenConverter.setAccessTokenConverter(tokenConverter);

            jwtAccessTokenConverter.setSigningKey(this.jwtKey);
            return jwtAccessTokenConverter;
        }

        @Bean
        public JwtTokenStore jwtTokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
            return new JwtTokenStore(jwtAccessTokenConverter);
        }

        @Bean
        public DefaultTokenServices defaultTokenServices(JwtTokenStore jwtTokenStore, JwtAccessTokenConverter jwtAccessTokenConverter, DryadClientDetailsServiceImpl dryadClientDetailsServiceImpl) {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(jwtTokenStore);
            tokenServices.setClientDetailsService(dryadClientDetailsServiceImpl);
            //support refresh token
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenEnhancer(jwtAccessTokenConverter);
            return tokenServices;
        }

    }
}